package com.mbigger.admin.service.impl;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.mbigger.admin.dao.AclMapper;
import com.mbigger.admin.dao.AclModuleMapper;
import com.mbigger.admin.dao.DeptMapper;
import com.mbigger.admin.dto.AclDto;
import com.mbigger.admin.dto.AclModuleLevelDto;
import com.mbigger.admin.dto.DeptLevelDto;
import com.mbigger.admin.entity.Acl;
import com.mbigger.admin.entity.AclModule;
import com.mbigger.admin.entity.Department;
import com.mbigger.admin.service.TreeService;
import com.mbigger.admin.util.LevelUtil;

@Service
public class TreeServiceImpl implements TreeService{

	@Autowired
	private DeptMapper deptMapper;
	@Autowired
	private AclModuleMapper aclModuleMapper;
	@Autowired
	private CoreServiceImpl coreService;
	@Autowired
	private AclMapper aclMapper;
	
    public List<AclModuleLevelDto> userAclTree(int userId) {
        List<Acl> userAclList = coreService.getUserAclList(userId);
        List<AclDto> aclDtoList = Lists.newArrayList();
        for (Acl acl : userAclList) {
            AclDto dto = AclDto.adapt(acl);
            dto.setHasAcl(true);
            dto.setChecked(true);
            aclDtoList.add(dto);
        }
        return aclListToTree(aclDtoList);
    }

	public List<DeptLevelDto> deptTree() {
		List<Department> deptList = deptMapper.getAllDept();

		List<DeptLevelDto> dtoList = Lists.newArrayList();
		for (Department dept : deptList) {
			DeptLevelDto dto = DeptLevelDto.adapt(dept);
			dtoList.add(dto);
		}
		return deptListToTree(dtoList);
	}

	public List<DeptLevelDto> deptListToTree(List<DeptLevelDto> deptLevelList) {
		if (CollectionUtils.isEmpty(deptLevelList)) {
			return Lists.newArrayList();
		}
		// level -> [dept1, dept2, ...] Map<String, List<Object>>
		Multimap<String, DeptLevelDto> levelDeptMap = ArrayListMultimap.create();
		List<DeptLevelDto> rootList = Lists.newArrayList();

		for (DeptLevelDto dto : deptLevelList) {
			levelDeptMap.put(dto.getLevel(), dto);
			if (LevelUtil.ROOT.equals(dto.getLevel())) {
				rootList.add(dto);
			}
		}
		// 按照seq从小到大排序
		Collections.sort(rootList, new Comparator<DeptLevelDto>() {
			public int compare(DeptLevelDto o1, DeptLevelDto o2) {
				return o1.getSeq() - o2.getSeq();
			}
		});
		// 递归生成树
		transformDeptTree(rootList, LevelUtil.ROOT, levelDeptMap);
		return rootList;
	}

	// level:0, 0, all 0->0.1,0.2
	// level:0.1
	// level:0.2
	public void transformDeptTree(List<DeptLevelDto> deptLevelList, String level,
			Multimap<String, DeptLevelDto> levelDeptMap) {
		for (int i = 0; i < deptLevelList.size(); i++) {
			// 遍历该层的每个元素
			DeptLevelDto deptLevelDto = deptLevelList.get(i);
			// 处理当前层级的数据
			String nextLevel = LevelUtil.calculateLevel(level, deptLevelDto.getId());
			// 处理下一层
			List<DeptLevelDto> tempDeptList = (List<DeptLevelDto>) levelDeptMap.get(nextLevel);
			if (CollectionUtils.isNotEmpty(tempDeptList)) {
				// 排序
				Collections.sort(tempDeptList, deptSeqComparator);
				// 设置下一层部门
				deptLevelDto.setDeptList(tempDeptList);
				// 进入到下一层处理
				transformDeptTree(tempDeptList, nextLevel, levelDeptMap);
			}
		}
	}

	public Comparator<DeptLevelDto> deptSeqComparator = new Comparator<DeptLevelDto>() {
		public int compare(DeptLevelDto o1, DeptLevelDto o2) {
			return o1.getSeq() - o2.getSeq();
		}
	};

	public List<AclModuleLevelDto> aclModuleListToTree(List<AclModuleLevelDto> dtoList) {
		if (CollectionUtils.isEmpty(dtoList)) {
			return Lists.newArrayList();
		}
		// level -> [aclmodule1, aclmodule2, ...] Map<String, List<Object>>
		Multimap<String, AclModuleLevelDto> levelAclModuleMap = ArrayListMultimap.create();
		List<AclModuleLevelDto> rootList = Lists.newArrayList();

		for (AclModuleLevelDto dto : dtoList) {
			levelAclModuleMap.put(dto.getLevel(), dto);
			if (LevelUtil.ROOT.equals(dto.getLevel())) {
				rootList.add(dto);
			}
		}
		Collections.sort(rootList, aclModuleSeqComparator);
		transformAclModuleTree(rootList, LevelUtil.ROOT, levelAclModuleMap);
		return rootList;
	}

	public void transformAclModuleTree(List<AclModuleLevelDto> dtoList, String level,
			Multimap<String, AclModuleLevelDto> levelAclModuleMap) {
		for (int i = 0; i < dtoList.size(); i++) {
			AclModuleLevelDto dto = dtoList.get(i);
			String nextLevel = LevelUtil.calculateLevel(level, dto.getId());
			List<AclModuleLevelDto> tempList = (List<AclModuleLevelDto>) levelAclModuleMap.get(nextLevel);
			if (CollectionUtils.isNotEmpty(tempList)) {
				Collections.sort(tempList, aclModuleSeqComparator);
				dto.setAclModuleList(tempList);
				transformAclModuleTree(tempList, nextLevel, levelAclModuleMap);
			}
		}
	}

	public Comparator<AclModuleLevelDto> aclModuleSeqComparator = new Comparator<AclModuleLevelDto>() {
		public int compare(AclModuleLevelDto o1, AclModuleLevelDto o2) {
			return o1.getSeq() - o2.getSeq();
		}
	};

	public List<AclModuleLevelDto> aclModuleTree() {
		List<AclModule> aclModuleList = aclModuleMapper.getAllAclModule();
		List<AclModuleLevelDto> dtoList = Lists.newArrayList();
		for (AclModule aclModule : aclModuleList) {
			dtoList.add(AclModuleLevelDto.adapt(aclModule));
		}
		return aclModuleListToTree(dtoList);
	}

	public List<AclModuleLevelDto> roleTree(int roleId) {
		// 1、当前用户已分配的权限点
		List<Acl> userAclList = coreService.getCurrentUserAclList();
		// 2、当前角色分配的权限点
		List<Acl> roleAclList = coreService.getRoleAclList(roleId);
		// 3、当前系统所有权限点
		List<AclDto> aclDtoList = Lists.newArrayList();

		Set<Integer> userAclIdSet = userAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());
		Set<Integer> roleAclIdSet = roleAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());

		List<Acl> allAclList = aclMapper.getAll();
		for (Acl acl : allAclList) {
			AclDto dto = AclDto.adapt(acl);
			if (userAclIdSet.contains(acl.getId())) {
				dto.setHasAcl(true);
			}
			if (roleAclIdSet.contains(acl.getId())) {
				dto.setChecked(true);
			}
			aclDtoList.add(dto);
		}
		return aclListToTree(aclDtoList);
	}

	public List<AclModuleLevelDto> aclListToTree(List<AclDto> aclDtoList) {
		if (CollectionUtils.isEmpty(aclDtoList)) {
			return Lists.newArrayList();
		}
		List<AclModuleLevelDto> aclModuleLevelList = aclModuleTree();

		Multimap<Integer, AclDto> moduleIdAclMap = ArrayListMultimap.create();
		for (AclDto acl : aclDtoList) {
			if (acl.getStatus() == 1) {
				moduleIdAclMap.put(acl.getAclModuleId(), acl);
			}
		}
		bindAclsWithOrder(aclModuleLevelList, moduleIdAclMap);
		return aclModuleLevelList;
	}

	public void bindAclsWithOrder(List<AclModuleLevelDto> aclModuleLevelList,
			Multimap<Integer, AclDto> moduleIdAclMap) {
		if (CollectionUtils.isEmpty(aclModuleLevelList)) {
			return;
		}
		for (AclModuleLevelDto dto : aclModuleLevelList) {
			List<AclDto> aclDtoList = (List<AclDto>) moduleIdAclMap.get(dto.getId());
			if (CollectionUtils.isNotEmpty(aclDtoList)) {
				Collections.sort(aclDtoList, aclSeqComparator);
				dto.setAclList(aclDtoList);
			}
			bindAclsWithOrder(dto.getAclModuleList(), moduleIdAclMap);
		}
	}

	public Comparator<AclDto> aclSeqComparator = new Comparator<AclDto>() {
		public int compare(AclDto o1, AclDto o2) {
			return o1.getSeq() - o2.getSeq();
		}
	};
}
